#pragma once

#include "crane/defs.hpp"

CRA_NS_BEGIN
namespace aio {

/// @brief 缓冲区基类
class Buffer {
protected:
    size_t size_    = 0;
    size_t limit_   = 0;
    size_t pos_     = 0;
    size_t mark_    = 0;

protected:

    // 析构函数, 设置为protected，避免用户直接使用此来析构子类。
    ~Buffer()
    {
        size_ = 0;
        limit_ = 0;
        pos_ = 0;
        mark_ = 0;
    }

public:
    Buffer() : size_(0), limit_(0), pos_(0), mark_(0) {}

    Buffer(size_t size) : size_(size), limit_(size), pos_(0), mark_(0) {}

    size_t size() const { return size_; }
    size_t limit() const { return limit_; }
    size_t position() const { return pos_; }

    size_t mark() const { return mark_; }

    size_t remaining() const { return limit_ - pos_; }
    
    Buffer & setMark() {
        mark_ = pos_;
        return *this;
    }

    Buffer & setPosition(size_t pos) {
        assert(pos <= limit_);
        pos_ = pos;
        return *this;
    }

    Buffer & setLimit(size_t limit) {
        assert(limit <= size_);
        limit_ = limit;
        return *this;
    }

    Buffer & clear() {
        pos_ = 0;
        limit_ = size_;
        mark_ = 0;
        return *this;
    }

    Buffer & flip() {
        limit_ = pos_;
        pos_ = 0;
        mark_ = 0;
        return *this;
    }

    Buffer & rewind() {
        mark_ = 0;
        pos_ = 0;
        return  *this;
    }

    Buffer & reset() {
        pos_ = mark_;
        return *this;
    }
}; // Buffer

/// @brief  缓存分配器
/// @tparam T  缓存元素类型
template<typename T>
class BufferAllocator {
public:
    T * allocate(size_t size) { return new T[size]; }
    void deallocate(T * ptr, size_t size)  { if ( ptr ) delete[] ptr; }
};

/// @brief 字节缓存
class ByteBuffer : public Buffer, private  BufferAllocator<char> {
    CRA_NONCOPYABLE(ByteBuffer)
private:
    char * data_    = nullptr;

public:
    ByteBuffer() {}
    ByteBuffer(size_t size);
    ByteBuffer(char * data, size_t size);
    ~ByteBuffer();

    ByteBuffer(ByteBuffer && other);
    ByteBuffer & operator=(ByteBuffer && other);

    char * data() { return data_;  }    
}; // ByteBuffer

CRA_INLINE
ByteBuffer::ByteBuffer(size_t size)
: Buffer(size), data_(allocate(size))
{
}

CRA_INLINE
ByteBuffer::ByteBuffer(char * data, size_t size)
: Buffer(size), data_(data)
{
}

CRA_INLINE
ByteBuffer::ByteBuffer(ByteBuffer && other)
: Buffer(other), data_(other.data_)
{
    other.data_ = nullptr;
    other.Buffer::~Buffer();
}

CRA_INLINE
ByteBuffer::~ByteBuffer()
{
    if ( data_) {
        deallocate(data_, size_);
        data_ = nullptr;
    }
}

CRA_INLINE
ByteBuffer & ByteBuffer::operator=(ByteBuffer && other)
{
    if (this != &other) {
        deallocate(data_, size_);
        data_ = other.data_;
        other.data_ = nullptr;
        other.Buffer::~Buffer();
    }
    return *this;
}


} // nio
CRA_NS_END
